package studio.raptor.dispatcher.server.service;

import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import studio.raptor.databus.command.EventMetaData;
import studio.raptor.dispatcher.server.graph.DirectGraph;
import studio.raptor.dispatcher.server.graph.EventDirectGraph;
import studio.raptor.dispatcher.server.sort.EventRelationship;

/**
 * @author jack
 * @since 1.0
 */
@Service
public class GraphService {

  private static final Logger log = LoggerFactory.getLogger(GraphService.class);


  @Autowired
  EventDirectGraph eventDirectGraph;

  @Autowired
  EventRelationship eventRelationship;


  /**
   * 保存事件到有向无环图中并排序.
   *
   * @param code 接口编码
   * @param event 事件元信息
   * @param status 事件状态
   */
  public void sortEvent(String code, EventMetaData event, String status) {
    String eventId = event.getBusinessNo();

    log.debug("the direct graph of consumer [{}] add event node[{}]", code);
    DirectGraph graph = eventDirectGraph.getDirectGraph(code);
    if (graph.containEvent(eventId)) {
      log.debug("the code:{},node [{}] exists in the graph ", code, eventId);
      return;
    }
    //1 从内存中获取事件的依赖关系
    Set<String> depends = eventRelationship.getDependEventId(code, event);
    if (log.isDebugEnabled()) {
      log.debug("the event:[{}],depend->[{}]", eventId, depends.toString());
    }
    //1.没有依赖，直接创建节点并与root节点建立关联
    if (depends.isEmpty()) {
      graph.addNode(eventId, status);
      return;
    }
    //2 事件节点保存到内存的有向无环图，并建立节点间的关联关系，过滤已经建立过关系的图
    graph.putEdges(eventId, status, depends);
  }


  /**
   * 根据接口编码获取当前接口下可以发送的任务集合.
   *
   * @param code 接口主题
   * @param status 事件状态
   * @param limit 获取事件最大数量
   * @return 可以被处理的事件id集合
   */
  public Set<String> fetchEvent(String code, String status, int limit) {
    DirectGraph graph = eventDirectGraph.getDirectGraph(code);
    Set<String> result = graph.fetchNodes(limit, status);
    return result;
  }

  /**
   * 批量更新图数据中节点的状态
   *
   * @param code 接口编码
   * @param eventIds 需要被更新的事件节点集合
   * @param status 更新后的节点状态
   */
  public void batchUpdateEventStatus(String code, Set<String> eventIds, String status) {
    DirectGraph graph = eventDirectGraph.getDirectGraph(code);
    for (String eventId : eventIds) {
      graph.updateEventNodeStatus(eventId, status);
    }
  }

  /**
   * 更新图数据中节点的状态
   *
   * @param code 接口编码
   * @param eventId 需要被更新的事件节点
   * @param status 更新后的节点状态
   */
  public void updateEventStatus(String code, String eventId, String status) {
    DirectGraph graph = eventDirectGraph.getDirectGraph(code);
    graph.updateEventNodeStatus(eventId, status);
  }

  /**
   * 删除图中的事件节点，更新事件的依赖关系
   * @param eventId 事件id
   * @param code 接口编码
   */
  public void deleteEvent(String eventId, String code) {
    DirectGraph graph = eventDirectGraph.getDirectGraph(code);
    //删除内存图中的节点
    graph.deleteNode(eventId);
    //删除内存的依赖关系
    eventRelationship.updateRelationship(eventId, code);
  }

}
